home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
GameKit
/
Examples
/
PacMan
/
Maze.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
7KB
|
291 lines
#import <stdio.h>
#import <libc.h>
#import "Maze.h"
#import "PacManGameBrain.h"
#import <appkit/appkit.h>
@implementation Maze
- init
{
char *appPath, *slashPos;
int i, j, k;
FILE *fp;
[super init];
// load image
mazeParts[1] = [NXImage findImageNamed:"Maze.tiff"];
mazeParts[2] = [NXImage findImageNamed:"MazeBig.tiff"];
scale = 1;
// get the path to the app wrapper (to find the maze file)
appPath = (char *)malloc(1024);
strcpy(appPath, NXArgv[0]);
if (slashPos = strrchr(appPath, '/')) {
slashPos[1] = '\0';
} else {
strcpy(appPath, "./");
}
strcat(appPath, "mazes");
// read in the maze data
fp = fopen(appPath, "r");
if (fp == NULL) fprintf(stderr, "PacMan: Cannot read maze data!\n");
for (i=0; i<MAZES; i++) {
for (j=BLOCK_HEIGHT-1; j>=0; j--) {
for (k=0; k<BLOCK_WIDTH; k++) {
mazes[i][k][j] = getc(fp);
switch(mazes[i][k][j]) { // handle special cases
case 'D' : { mazes[i][k][j] = 5; // Door
break; }
case '>' : { mazes[i][k][j] = 26; // door cap
break; }
case '<' : { mazes[i][k][j] = 27; // door cap
break; }
case ']' : { mazes[i][k][j] = 33; // end cap
break; }
case '[' : { mazes[i][k][j] = 32; // end cap
break; }
case ' ' : { mazes[i][k][j] = 28; // dot
break; }
case 'O' : { mazes[i][k][j] = 29; // power dot
break; }
case '|' : { mazes[i][k][j] = 31; // vert wall
break; }
case '-' : { mazes[i][k][j] = 30; // horiz wall
break; }
case '^' : { mazes[i][k][j] = 34; // end cap
break; }
case 'P' : { mazes[i][k][j] = 7; // player (blank image)
break; }
case 'G' : { mazes[i][k][j] = 10; // ghost (blank image)
break; }
case '+' : { mazes[i][k][j] = 8; // blank (inside cage)
break; }
default : { mazes[i][k][j] -= 'a'; // get index
break; }
}
}
getc(fp);
}
}
fclose(fp);
// initizlize other instance vars.
[self makeMaze:1];
powerDotShown = YES;
visibleMaze = YES;
return self;
}
- render:(NXRect *)rect at:(NXPoint *)pos // used to render in another view
{
int j, k;
NXRect from, check;
NXPoint pos2;
if (!visibleMaze) return self;
for (j=0; j<BLOCK_HEIGHT; j++) {
pos2.y = j * GHOST_SIZE * scale + pos->y;
for (k=0; k<BLOCK_WIDTH; k++) {
if ((maze[k][j] != POWER) || powerDotShown) { // if power dot
// blinked off, we don't render it.
NXSetRect(&check, k * GHOST_SIZE, j * GHOST_SIZE,
GHOST_SIZE, GHOST_SIZE);
if (NXIntersectsRect(&check, rect)) { // only draw maze bits
// in the rects that intersect the rect passed to us
NXSetRect(&from,
(maze[k][j] % PER_ROW) * GHOST_SIZE * scale,
(maze[k][j] / PER_ROW) * GHOST_SIZE * scale,
GHOST_SIZE * scale, GHOST_SIZE * scale);
pos2.x = k * GHOST_SIZE * scale + pos->x;
[mazeParts[scale] composite:NX_SOVER
fromRect:&from toPoint:&pos2];
} } } }
return self;
}
- makeMaze:(int)num
{ // build a maze from the template; fill it with dots, set up new player and
// ghost positions, etc.
int j, k;
int ghost = 0;
int pdot = 0;
dots = 0;
if ((num >= 0) && (num < MAZES)) { // make sure in range
mazeNum = num;
player[0] = -32; player[1] = -32; // sum is neg if no player spot found
// set up player/ghost/power dot position, etc. for maze.
for (j=0; j<BLOCK_HEIGHT; j++) {
for (k=0; k<BLOCK_WIDTH; k++) {
maze[k][j] = mazes[num][k][j];
switch (maze[k][j]) {
case GHDOOR : { door[0] = k; // door for ghosts
door[1] = j; break; }
case PLAYER : { player[0] = k; // Player
player[1] = j;
maze[k][j] = EMPTY; break; }
case GHOST : { ghosts[ghost * 2] = k; // Ghost
ghosts[ghost * 2 + 1] = j;
maze[k][j] = EMPTY;
if (++ghost > MAX_GHOSTS) { fprintf(stderr,
"Maze %d has too many ghosts.\n", num); }
break; }
case POWER : { power[pdot * 2] = k; // Power Dot
power[pdot * 2 + 1] = j; dots++;
if (++pdot > MAX_POWER_DOTS) { fprintf(stderr,
"Maze %d has too many power dots.\n", num); }
break; }
case DOT : { dots++; // Normal Dot
break; }
default : { break; } // do nothing
}
}
}
if (!ghost) { fprintf(stderr, "Maze %d has no ghosts.\n", num); }
if (!pdot) { fprintf(stderr, "Maze %d has no power dots.\n", num); }
if (player[0]+player[1] < 0) {
fprintf(stderr, "Maze %d has no player.\n", num); }
}
return self;
}
- playerPosition:(int *)x :(int *)y // return x, y of player/fruit
{
*x = player[0] * GHOST_SIZE; *y = player[1] * GHOST_SIZE;
return self;
}
- doorPosition:(int *)x :(int *)y // return x, y of door to ghost chamber
{
*x = door[0] * GHOST_SIZE; *y = door[1] * GHOST_SIZE;
return self;
}
- (const int *)powerDot // return pointer to power array
{
return power;
}
- (const int *)ghosts // return pointer to ghosts array
{
return ghosts;
}
- (BOOL)powerDotAt:(int)x :(int)y // return YES if power dot in block
{
// only have to be 1/2 way into block to eat dot:
int basex = x / GHOST_SIZE + ((x % GHOST_SIZE) > (GHOST_SIZE / 2));
int basey = y / GHOST_SIZE + ((y % GHOST_SIZE) > (GHOST_SIZE / 2));
if (maze[basex][basey] == POWER) { // munch power dot
[[[NXApp delegate] scoreKeeper] addToScore:POWERDOTPOINTS];
maze[basex][basey] = EMPTY;
dots--;
dotx = basex; doty = basey; // save them away
return YES;
}
return NO;
}
- (BOOL)eatDotAt:(int)x :(int)y // return YES if OK, NO if no dot was there
{
int basex = x / GHOST_SIZE;
int basey = y / GHOST_SIZE;
int dx = x % GHOST_SIZE;
int dy = y % GHOST_SIZE;
if (!dx) { // in a vertical column or corner/junction
if (dy > GHOST_SIZE / 2) basey++;
} else { // on a horiz. row
if (dx > GHOST_SIZE / 2) basex++;
}
if (maze[basex][basey] == DOT) { // munch dot
[[[NXApp delegate] scoreKeeper] addToScore:DOTPOINTS];
maze[basex][basey] = EMPTY;
dots--;
dotx = basex; doty = basey; // save them away
return YES;
}
return NO;
}
- (int)dots // return the number of dots left in maze
{
return dots;
}
- lastDot:(int *)xx :(int *)yy
{
*xx = dotx * GHOST_SIZE;
*yy = doty * GHOST_SIZE;
return self;
}
- (BOOL)playerWall:(float)x :(float)y // YES if player can't be in block
{
int mazex = x / GHOST_SIZE;
int mazey = y / GHOST_SIZE;
if ((maze[mazex][mazey] == EMPTY) ||
(maze[mazex][mazey] == DOT) ||
(maze[mazex][mazey] == POWER)) return NO;
return YES;
}
- (BOOL)monsterWall:(float)x :(float)y // YES if ghost can't be in block
{
int mazex = x / GHOST_SIZE;
int mazey = y / GHOST_SIZE;
if ((maze[mazex][mazey] == EMPTY) ||
(maze[mazex][mazey] == DOT) ||
(maze[mazex][mazey] == GHDOOR) ||
(maze[mazex][mazey] == POWER)) return NO;
return YES;
}
- blinkPowerDot // toggle ON/OFF state of power dots
{
powerDotShown = !powerDotShown;
return self;
}
- visible:(BOOL)flag // used to tell us if the maze is visible
{
visibleMaze = flag;
return self;
}
- (BOOL)isVisible; // used to tell others if maze is visible
{ return visibleMaze; }
- (int)scale
{
return scale;
}
- setScale:(int)newScale
{
if ((newScale < 1) || (newScale > 2)) return self;
scale = newScale;
return self;
}
@end